﻿using Asp.Versioning;
using FlyingEye.ControllerServices;
using FlyingEye.Exceptions;
using FlyingEye.Monitors.Models;
using FlyingEye.Monitors.Repositories;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace FlyingEye.Controllers
{
    [Authorize]
    [ControllerName("ReadNumericValueTask")]
    [ApiVersion("1.0")]
    [Route("api/device-monitor-service/v{version:apiVersion}/read-numeric-value-tasks")]
    public class ReadNumericValueTaskController : DefaultController
    {
        private readonly IReadNumericValueTaskRepository _readNumericValueTaskRepository;

        private readonly INumericValueMonitorClientRepository _numericValueMonitorClientRepository;

        private readonly INumericValueMonitorGroupRepository _numericValueMonitorGroupRepository;

        public ReadNumericValueTaskController(
            IReadNumericValueTaskRepository readNumericValueTaskRepository,
            INumericValueMonitorClientRepository numericValueMonitorClientRepository,
            INumericValueMonitorGroupRepository numericValueMonitorGroupRepository)
        {
            _readNumericValueTaskRepository = readNumericValueTaskRepository;
            _numericValueMonitorClientRepository = numericValueMonitorClientRepository;
            _numericValueMonitorGroupRepository = numericValueMonitorGroupRepository;
        }

        [HttpGet("{id}/numeric-value-monitor-clients")]
        public async Task<ActionResult<List<NumericValueMonitorClientResponse>>> GetNumericValueMonitorClientsAsync(Guid id)
        {
            return await this.GetInvokeAsync(async () =>
            {
                var list = await _numericValueMonitorClientRepository.GetListAsync(item => item.ReadNumericValueTaskId == id);
                return ObjectMapper.Map<List<NumericValueMonitorClientModel>, List<NumericValueMonitorClientResponse>>(list);
            });
        }

        [HttpGet("{id}/numeric-value-monitor-groups")]
        public async Task<ActionResult<List<NumericValueMonitorGroupResponse>>> GetNumericValueMonitorGroupsAsync(Guid id)
        {
            return await this.GetInvokeAsync(async () =>
            {
                var list = await _numericValueMonitorGroupRepository.GetListAsync(item => item.ReadNumericValueTaskId == id);
                return ObjectMapper.Map<List<NumericValueMonitorGroupModel>, List<NumericValueMonitorGroupResponse>>(list);
            });
        }

        [HttpGet("{id}", Name = "GetByReadNumericValueTaskId")]
        public async Task<ActionResult<ReadNumericValueTaskResponse>> GetAsync(Guid id)
        {
            return await this.GetInvokeAsync(async () =>
            {
                var model = await _readNumericValueTaskRepository.GetAsync(id);

                return ObjectMapper.Map<ReadNumericValueTaskModel, ReadNumericValueTaskResponse>(model);
            });
        }

        [HttpGet]
        public async Task<ActionResult<List<ReadNumericValueTaskResponse>>> GetListAsync()
        {
            return await this.GetInvokeAsync(async () =>
            {
                var list = await _readNumericValueTaskRepository.GetListAsync();
                return ObjectMapper.Map<List<ReadNumericValueTaskModel>, List<ReadNumericValueTaskResponse>>(list);
            });
        }

        [HttpPut]
        public async Task<ActionResult<ReadNumericValueTaskResponse>> UpdateAsync([FromBody] UpdateReadNumericValueTaskRequest request)
        {
            if (request.DeviceClientId == Guid.Empty)
            {
                throw new AppArgumentValidationException("设备客户端 ID 不能为空");
            }

            if (string.IsNullOrWhiteSpace(request.TaskName))
            {
                throw new AppArgumentValidationException("任务名称不能为空");
            }

            if (string.IsNullOrWhiteSpace(request.DeviceName))
            {
                throw new AppArgumentValidationException("设备名称不能为空");
            }

            if (string.IsNullOrWhiteSpace(request.Address))
            {
                throw new AppArgumentValidationException("地址不能为空");
            }

            if (string.IsNullOrWhiteSpace(request.DataType))
            {
                throw new AppArgumentValidationException("数据类型不能为空");
            }

            if (request.Interval < 100)
            {
                throw new AppArgumentValidationException("读取间隔必须大于 100 毫秒");
            }

            if (request.Id == Guid.Empty)
            {
                throw new AppArgumentValidationException("Id 不能为空");
            }

            return await this.PutInvokeAsync(async () =>
            {
                var model = ObjectMapper.Map<UpdateReadNumericValueTaskRequest, ReadNumericValueTaskModel>(request);
                var result = await _readNumericValueTaskRepository.UpdateAsync(model);
                return ObjectMapper.Map<ReadNumericValueTaskModel, ReadNumericValueTaskResponse>(result);
            });
        }

        [HttpPost]
        public async Task<ActionResult<ReadNumericValueTaskResponse>> InsertAsync([FromBody] CreateReadNumericValueTaskRequest request)
        {
            if (request.DeviceClientId == Guid.Empty)
            {
                throw new AppArgumentValidationException("设备客户端 ID 不能为空");
            }

            if (string.IsNullOrWhiteSpace(request.TaskName))
            {
                throw new AppArgumentValidationException("任务名称不能为空");
            }

            if (string.IsNullOrWhiteSpace(request.DeviceName))
            {
                throw new AppArgumentValidationException("设备名称不能为空");
            }

            if (string.IsNullOrWhiteSpace(request.Address))
            {
                throw new AppArgumentValidationException("地址不能为空");
            }

            if (string.IsNullOrWhiteSpace(request.DataType))
            {
                throw new AppArgumentValidationException("数据类型不能为空");
            }

            if (request.Interval <= 100)
            {
                throw new AppArgumentValidationException("读取间隔必须大于 200 毫秒");
            }

            return await this.InsertInvokeAsync(async () =>
            {
                var model = ObjectMapper.Map<CreateReadNumericValueTaskRequest, ReadNumericValueTaskModel>(request);
                var result = await _readNumericValueTaskRepository.InsertAsync(model);
                return ObjectMapper.Map<ReadNumericValueTaskModel, ReadNumericValueTaskResponse>(result);
            }, "GetByReadNumericValueTaskId", x => new { x.Id });
        }

        [HttpDelete("{id}")]
        public async Task<NoContentResult> DeleteAsync(Guid id)
        {
            return await this.DeleteInvokeAsync(async () =>
            {
                await _readNumericValueTaskRepository.DeleteAsync(id);
            });
        }
    }
}
